#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <config.h>
#include <network.h>
#include "client.h"
#include "tools.h"

NetWork* cmd_nw = NULL;
char cmd_buf[256];
char data_buf[1024];

void* _find_server(void* arg)
{
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(6677);
	addr.sin_addr.s_addr = htonl(*(int*)arg);
	
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return NULL;
	}
	
	if(0 == connect(sockfd,(struct sockaddr*)&addr,sizeof(addr)))
	{
		printf("server ip:%s\n",inet_ntoa(addr.sin_addr));
		nsend(cmd_nw,"quit",5);
	}
	
	close(sockfd);
}

int find_server(void)
{
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return -1;
	}
	
	struct in_addr ip,broad,mask;
	get_ip_broad_mask(sockfd,&ip,&broad,&mask);  
	
	int min = ntohl(ip.s_addr)&ntohl(mask.s_addr);
	int max = ntohl(broad.s_addr);

	for(int i=min; i<max; i++)
	{
		pthread_t pid;
		pthread_create(&pid,NULL,_find_server,&i);
		usleep(100);
	}
	
	sleep(3);
	close(sockfd);
}

void init_client(void)
{
	cmd_nw = open_network('c',SOCK_STREAM,SERVER_IP,PORT);
	if(NULL == cmd_nw)
	{
		printf("open_network error!\n");
		_exit(-1);
	}
}

void list_client(void)
{
	printf("func:%s cmd:%s\n",__func__,cmd_buf);
	nrecv(cmd_nw,cmd_buf,sizeof(cmd_buf));
	printf("cmd_buf:%s %hu\n",cmd_buf,atoi(cmd_buf+10));
	if(0 != strncmp("data port:",cmd_buf,10))
	{
		perror("list start error !\n");
		return;
	}
	
	char data_buf[1024] = {};
	NetWork* data_nw = open_network('c',FILE_MODE,SERVER_IP,atoi(cmd_buf+10));
	printf("--------------------\n");
	while(nrecv(data_nw,data_buf,sizeof(data_buf)))
	{
		printf("%s",data_buf);
	}
	close_network(data_nw);
	printf("\n");
	
	nrecv(cmd_nw,cmd_buf,sizeof(cmd_buf));
	if(0 != strcmp("list end",cmd_buf))
	{
		perror("list end error!\n");
		return;
	}
	
}

void get_client(void)
{
	printf("func:%s arg:%s\n",__func__,cmd_buf);
	nrecv(cmd_nw,cmd_buf,sizeof(cmd_buf));
	if(0 != strncmp("data port:",cmd_buf,9))
	{
		perror("get file start error !\n");
		printf("请检查文件名是否正确!\n");
		return;
	}
	
	
	NetWork* data_nw = open_network('c',FILE_MODE,SERVER_IP,atoi(cmd_buf+9));
	int fd = open(cmd_buf+4,O_WRONLY|O_CREAT|O_TRUNC,0644);
	if(0 > fd)
	{
		perror("get file open");
		return;
	}
	
	int ret = 0;
	while(ret = nrecv(data_nw,data_buf,sizeof(data_buf)))
	{
		write(fd,data_buf,ret);
	}
	close(fd);
	close_network(data_nw);
	
	nrecv(cmd_nw,cmd_buf,sizeof(cmd_buf));
	if(0 != strncmp("get end:",cmd_buf,8))
	{
		perror("get file end error!\n");
		return;
	}
	
	if(NULL == file_md5(cmd_buf+4,data_buf))
	{
		perror("file md5 failed!\n");
		return;
	}
	
	if(0 == strncmp(cmd_buf+8,data_buf,16))
	{
		printf("文件下载成功!\n");
	}
	else
	{
		printf("文件下载不完整，请重新下载!\n");
	}
}
void put_client(void)
{
	printf("func:%s arg:%s\n",__func__,cmd_buf);
	nrecv(cmd_nw,cmd_buf,sizeof(cmd_buf));
	if(0 != strncmp("put port:",cmd_buf,9))
	{
		perror("put start error !\n");
		return;
	}
	
	
	NetWork* data_nw = open_network('c',FILE_MODE,SERVER_IP,atoi(cmd_buf+9));
	int fd = open(cmd_buf+4,O_WRONLY|O_CREAT|O_TRUNC,0644);
	if(0 > fd)
	{
		perror("get file open");
		printf("请检查文件名是否正确!\n");
		return;
	}
	
	int ret = 0;
	while(ret = read(fd,data_buf,sizeof(data_buf)))
	{
		nsend(data_nw,data_buf,ret);
	}
	close_network(data_nw);
	close(fd);
	
	if(NULL == file_md5(cmd_buf+4,data_buf))
	{
		perror("file md5 failed!\n");
		return;
	}
	
	strcpy(cmd_buf,"put end:");
	strncat(cmd_buf,data_buf,16);
	nsend(cmd_nw,cmd_buf,strlen(cmd_buf)+1);
	
	nrecv(cmd_nw,cmd_buf,sizeof(cmd_buf));
	if(0 == strcmp("put ok!",cmd_buf))
	{
		printf("上传文件成功!\n");
	}
	else
	{
		printf("上传文件不完整，请重新上传成功!\n");
	}
}

void start_client(void)
{
	for(;;)
	{
		printf(">");
		get_str(cmd_buf,sizeof(cmd_buf));
		if(0 == strncmp("list",cmd_buf,4))
		{
			nsend(cmd_nw,cmd_buf,strlen(cmd_buf)+1);
			list_client();
		}
		else if(0 == strncmp("get",cmd_buf,3))
		{
			nsend(cmd_nw,cmd_buf,strlen(cmd_buf)+1);
			get_client();
		}
		else if(0 == strncmp("put",cmd_buf,3))
		{
			nsend(cmd_nw,cmd_buf,strlen(cmd_buf)+1);
			put_client();
		}
		else if(0 == strncmp("quit",cmd_buf,4))
		{
			nsend(cmd_nw,cmd_buf,strlen(cmd_buf)+1);
			exit_client();
		}
		else
		{
			printf("-----cmd list-----\n");
			printf("list\n");
			printf("put filename\n");
			printf("get filename\n");
			printf("quit\n");
		}
	}
}

void exit_client(void)
{
	close_network(cmd_nw);
	_exit(0);
}
